package com.landinfo.web.rest;

import javax.xml.bind.*;
import javax.xml.namespace.QName;
import java.io.ByteArrayOutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by ziqilv on 2017/7/4.
 */
public class JaxbHelper {
    static Map<String, JAXBContext> jaxbContextMap = new HashMap<String, JAXBContext>();

    /**
     * java实体类转xml
     */
    public static String toXML(Object obj, String encode, boolean format, boolean fragment) {
        try {
            JAXBContext jaxbContext = jaxbContextMap.get(obj.getClass().getName());
            if(jaxbContext == null){
                // 如果每次都调用JAXBContext.newInstance方法，会导致性能急剧下降
                jaxbContext = JAXBContext.newInstance(obj.getClass());
                jaxbContextMap.put(obj.getClass().getName(), jaxbContext);
            }

            Marshaller marshaller = jaxbContext.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_ENCODING, encode);           // 编码格式
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, format);   // 是否格式化生成的xml串
            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, fragment);         // 是否省略xm头声明信息
            StringWriter writer = new StringWriter();
            marshaller.marshal(obj, writer);
            return writer.toString();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

//
//        JAXBContext context = jaxbContextMap.get(obj.getClass().getName());
//        // 创建QName，这个是关键，有了这个就不要使用@XmlRootElement注解了，关于QName的资料大家自己网上找，这里不赘述
//        QName q = new QName("http://ws.test.com", obj.getClass().getName());
//        JAXBElement<Object> jaxbPerson = new JAXBElement<Object>(q, obj.getClass(), obj);
//        Marshaller m = null;
//        try {
//            m = context.createMarshaller();
//        } catch (JAXBException e) {
//            e.printStackTrace();
//        }
//        StringWriter sw = new StringWriter();
//        try {
//            m.marshal(jaxbPerson, sw);
//        } catch (JAXBException e) {
//            e.printStackTrace();
//        }
//        // 输出转换后的XML代码
//        return (sw.toString());
    }


    /**
     * 序列化XML
     * @param <T>
     * @param
     * @return
     * @throws JAXBException
     * @throws UnsupportedEncodingException
     */
    public static <T> String Marshal(T t,Class c) throws JAXBException, UnsupportedEncodingException
    {
        JAXBContext context = JAXBContext.newInstance(c);
        Marshaller marshaller = context.createMarshaller();
        //Validator v=context.createValidator();
        //v.setProperty("", "");
        //v.setProperty("", "");
        marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");        //编码格式
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);   //格式化XML
        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);

        QName q = new QName("", c.getSimpleName());
        JAXBElement<T> rootElement = new JAXBElement<T>(q,c, t);


        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        marshaller.marshal(rootElement, outputStream);


        return outputStream.toString("UTF-8");
    }

    /**
     * xml转java实体类
     */
    @SuppressWarnings("unchecked")
    public static <T> T fromXML(String xml, Class<T> valueType) {
        try {
            JAXBContext jaxbContext = jaxbContextMap.get(valueType.getName());
            if (jaxbContext == null) {
                jaxbContext = JAXBContext.newInstance(valueType);
                jaxbContextMap.put(valueType.getName(), jaxbContext);
            }
            Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
            return (T) unmarshaller.unmarshal(new StringReader(xml));
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }
}
